package cn.com.dealme.nutz.processor;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import org.apache.commons.validator.Validator;
import org.apache.commons.validator.ValidatorResources;
import org.nutz.lang.Lang;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.ActionContext;
import org.nutz.mvc.ActionInfo;
import org.nutz.mvc.NutConfig;
import org.nutz.mvc.impl.processor.AbstractProcessor;
import org.xml.sax.SAXException;

import cn.com.dealme.error.ErrorMap;
import cn.com.dealme.error.ErrMsgManager;
import cn.com.dealme.nutz.validation.HttpRequestMapAdaptor;
import cn.com.dealme.nutz.validation.ValidateBy;
import cn.com.dealme.nutz.validation.ValidateFailDispatcher;

public class ValidateProcessor extends AbstractProcessor {

	private static final Log log = Logs.getLog(ValidateProcessor.class);

	private static boolean validable = false;

	private static ValidatorResources validatorResources;
	
	private ValidateFailDispatcher failDispatcher;

	@Override
	public void init(NutConfig config, ActionInfo ai) throws Throwable {
		initValidatorResources(config, ai);
		failDispatcher = new ValidateFailDispatcher(ai.getFailView());
	}

	public void process(ActionContext ac) throws Throwable {
		if (!validable) {
			doNext(ac);
			return;
		}
		Validator validator = new Validator(validatorResources, ac.getPath());
		Map<String, String> bean = new HttpRequestMapAdaptor<String, String>(ac
				.getRequest());
		validator.setParameter(Validator.BEAN_PARAM, bean);
		Map<String, String> errMap = new ErrorMap<String, String>();
		validator.setParameter(ErrorMap.class.getName(), errMap);
		validator.validate();
		if (0 != errMap.size()) {
			failDispatcher.dispatch(ac, errMap);
		} else {
			doNext(ac);
		}
	}

	protected void initValidatorResources(NutConfig config, ActionInfo ai) {
		if (null == validatorResources) {
			ValidateBy vb = config.getMainModule().getAnnotation(
					ValidateBy.class);
			if (null == vb || null == vb.args() || 0 == vb.args().length)
				return;
			validable = true;
			readConfigFile(vb.args(), vb.errs());
		}
	}

	protected void readConfigFile(String[] files, String[] errs) {
		InputStream[] isArr = new InputStream[files.length];
		int index = 0;
		for (String file : files) {
			isArr[index] = this.getClass().getClassLoader()
					.getResourceAsStream(file);
			index++;
		}
		try {
			validatorResources = new ValidatorResources(isArr);
			if (log.isDebugEnabled()) {
				log.debug("Success to read and parse files ["
						+ Lang.concat(files) + "]");
			}
			for (String errFile : errs) {
				ErrMsgManager.load(this.getClass().getClassLoader()
						.getResourceAsStream(errFile));
			}
			if (log.isDebugEnabled()) {
				log.debug("Success to read and parse files ["
						+ Lang.concat(errs) + "]");
			}
		} catch (IOException e) {
			throw new RuntimeException("Fail to read files ["
					+ Lang.concat(files) + Lang.concat(errs) + "]", e);
		} catch (SAXException e) {
			throw new RuntimeException("Fail to parse files ["
					+ Lang.concat(files) + "]", e);
		}
	}

}
